home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DJGPP
/
CBGRX103.ZIP
/
contrib
/
libgrx
/
fntool
/
readbdf.c
< prev
next >
Wrap
Text File
|
1993-12-06
|
7KB
|
296 lines
#include "fntool.h"
typedef struct {
int bbw,bbh;
int bbx,bby;
} bbox;
static char **bmp;
static bbox fontbb;
static bbox charbb;
static int ascent;
static int descent;
static int defchar;
static void badbdf(char *msg)
{
fatalerr("invalid \".bdf\" file: \"%s\" -- %s",inname,msg);
}
static void readbitmap(void)
{
char *bp;
int ww = charbb.bbw;
int hh = charbb.bbh;
int y0 = fontbb.bbh - hh - (charbb.bby - fontbb.bby);
int x,y,bits;
if((charbb.bbw > fontbb.bbw) || (charbb.bbh > fontbb.bbh))
badbdf("bounding box error");
if((charbb.bbx < fontbb.bbx) || (charbb.bby < fontbb.bby))
badbdf("bounding box error");
if(bmp == NULL)
bmp = makebytemap(fontbb.bbw,fontbb.bbh);
setbytemap(bmp,0,0,0,fontbb.bbw,fontbb.bbh);
for(y = 0; y < hh; y++) {
bp = readline();
for(bits = x = 0; x < ww; x++) {
if((x & 3) == 0) {
bits = *bp++;
if(!isxdigit(bits)) {
if(x == 0) badbdf("invalid bitmap digit");
bits = 0;
}
else if(isdigit(bits)) bits -= '0';
else if(isupper(bits)) bits -= ('A' - 10);
else bits -= ('a' - 10);
}
bmp[y0+y][x] = (bits & 8) ? 1 : 0;
bits <<= 1;
}
}
}
static chr *buildchar(chr *temp)
{
int wdt = temp->width;
int pos = 0;
int cpy = charbb.bbw;
chr *result;
if(charbb.bbx > 0)
pos = charbb.bbx;
else if(charbb.bbx < 0)
wdt -= charbb.bbx;
if((pos + cpy) > wdt) wdt = pos + cpy;
temp->width = wdt;
temp->bmp = makebytemap(wdt,fnt.height);
copybytemap(temp->bmp,pos,0,bmp,0,0,cpy,fontbb.bbh);
result = safemalloc(sizeof(chr));
*result = *temp;
return(result);
}
static void readchar(void)
{
char *buff;
chr *cp,newch;
chr *prv,*nxt;
memset(&newch,0,sizeof(chr));
newch.code = (-1);
charbb = fontbb;
for( ; ; ) {
buff = readline();
if(strmatch(buff,"ENCODING")) {
sscanf(buff,"ENCODING %d",&newch.code);
continue;
}
if(strmatch(buff,"DWIDTH")) {
sscanf(buff,"DWIDTH %d",&newch.width);
continue;
}
if(strmatch(buff,"BBX")) {
sscanf(buff,
"BBX %d %d %d %d",
&charbb.bbw,&charbb.bbh,&charbb.bbx,&charbb.bby
);
continue;
}
if(strmatch(buff,"BITMAP")) {
readbitmap();
break;
}
}
if(newch.code < 0) return;
cp = buildchar(&newch);
for(prv = NULL,nxt = fnt.chars; nxt != NULL; prv = nxt,nxt = nxt->next) {
if(nxt->code == cp->code) badbdf("repeated character");
if(nxt->code > cp->code) break;
}
cp->next = nxt;
*(prv ? &prv->next : &fnt.chars) = cp;
}
static void scanstr(char *line,char *buf)
{
if((line = strchr(line,'"')) != NULL) for( ; ; ) {
if(*++line != '"') {
*buf++ = *line;
if(*line == '\0') break;
continue;
}
if(line[1] == '"') {
*buf++ = '"';
line++;
continue;
}
break;
}
*buf = '\0';
}
static void readfont(void)
{
char *buff;
char token[100];
int ii;
bmp = NULL;
for( ; ; ) {
buff = readline();
if(strmatch(buff,"FONTBOUNDINGBOX")) {
sscanf(buff,
"FONTBOUNDINGBOX %d %d %d %d",
&fontbb.bbw,&fontbb.bbh,&fontbb.bbx,&fontbb.bby
);
if(fontbb.bbh > fnt.height) fnt.height = fontbb.bbh;
continue;
}
if(strmatch(buff,"FAMILY_NAME")) {
scanstr(buff,fnt.family);
continue;
}
if(strmatch(buff,"WEIGHT_NAME")) {
scanstr(buff,token);
if(strmatch(token,"bold"))
strcpy(fnt.weight,"bold");
else if(strmatch(token,"thin"))
strcpy(fnt.weight,"thin");
continue;
}
if(strmatch(buff,"SLANT")) {
scanstr(buff,token);
switch(tolower(token[0])) {
case 'i':
case 'o':
strcpy(fnt.slant,"ital");
break;
}
continue;
}
if(strmatch(buff,"SPACING")) {
scanstr(buff,token);
switch(tolower(token[0])) {
case 'p':
fnt.isfixed = 0;
break;
case 'c':
case 'm':
fnt.isfixed = 1;
break;
}
continue;
}
if(strmatch(buff,"PIXEL_SIZE")) {
sscanf(buff,"PIXEL_SIZE %d",&ii);
if(ii > fnt.height) fnt.height = ii;
continue;
}
if(strmatch(buff,"FONT_DESCENT")) {
sscanf(buff,"FONT_DESCENT %d",&descent);
continue;
}
if(strmatch(buff,"FONT_ASCENT")) {
sscanf(buff,"FONT_ASCENT %d",&ascent);
continue;
}
if(strmatch(buff,"DEFAULT_CHAR")) {
sscanf(buff,"DEFAULT_CHAR %d",&defchar);
continue;
}
if(strmatch(buff,"FONT ")) {
strcat(notes,buff);
continue;
}
if(strmatch(buff,"COPYRIGHT")) {
strcat(notes,buff);
continue;
}
if(strmatch(buff,"COMMENT")) {
strcat(notes,&buff[8]);
continue;
}
if(strmatch(buff,"STARTCHAR")) {
readchar();
buff = readline();
if(!strmatch(buff,"ENDCHAR")) badbdf("missing \"ENDCHAR\" line");
continue;
}
if(strmatch(buff,"ENDFONT")) break;
}
if(bmp != NULL) free(bmp);
}
static void fillblank(void)
{
chr *cp,*defc,*new;
defc = getchr(defchar);
if(defc == NULL) defc = getchr(' ');
if(defc == NULL) defc = getchr(0);
if(defc == NULL) defc = fnt.chars;
fnt.minchar = fnt.chars->code;
for(cp = fnt.chars; cp != NULL; cp = cp->next) {
if((cp->next != NULL) && ((cp->code + 1) != cp->next->code)) {
new = safemalloc(sizeof(chr));
*new = *defc;
new->bmp = makebytemap(defc->width,fnt.height);
copybytemap(new->bmp,0,0,defc->bmp,0,0,defc->width,fnt.height);
new->code = cp->code + 1;
new->next = cp->next;
cp->next = new;
}
fnt.maxchar = cp->code;
}
}
static void fixwidth(void)
{
chr *cp;
char **newbmp;
int pad;
computewidth();
if(fnt.maxwidth == fnt.minwidth) return;
for(cp = fnt.chars; cp != NULL; cp = cp->next) {
if(cp->width == fnt.maxwidth) continue;
pad = fnt.maxwidth - cp->width;
if((pad & 1) != 0) {
int maxcol = -1;
int mincol = cp->width + 1;
int ii;
for(ii = 0; ii < cp->width; ii++) {
if(colbit(cp->bmp,ii)) {
if(ii > maxcol) maxcol = ii;
if(ii < mincol) mincol = ii;
}
}
if(maxcol >= mincol) {
if(mincol > (cp->width - maxcol - 1))
pad >>= 1;
else pad = (pad >> 1) + 1;
}
}
else pad >>= 1;
newbmp = makebytemap(fnt.maxwidth,fnt.height);
copybytemap(newbmp,pad,0,cp->bmp,0,0,cp->width,fnt.height);
free(cp->bmp);
cp->bmp = newbmp;
cp->width = fnt.maxwidth;
}
}
void readbdf()
{
ascent = 0;
descent = 0;
defchar = 0;
readfont();
fillblank();
if(fnt.isfixed) fixwidth();
fnt.baseline = fontbb.bbh + fontbb.bby;
fnt.undwidth = (fnt.height / 20) + 1;
}